

#include "unity.h"
#include "unity_fixture.h"

#include <ICC/Connector.h>
#include <ICC/Slot.h>

#include "Debug.h"
#include "BSP_Sleep.h"

#include <HID/command.h>
#include <HID/HIDiClass.h>
#include <HID/SIM.h>
#include <HID/HIDBLE.h>
#include "ReaderHidBLE.h"

extern slot_t Slot[1];

#if 0
#include "serialization/asn1.h"
#include "serialization/t1.h"
#include "router/router.h"

/*============================================================================================*/
typedef struct {
	t1_inf_t inf;
    uint16_t length;
	uint8_t payload[512];
}router_frame_t;

int router_queue_push(uint8_t src, uint8_t dest, uint8_t reply, void* payload, uint16_t length);

void router_frame_reset(router_frame_t* frame){
	memset(&frame->inf, 0, sizeof(t1_inf_t));
	memset(frame->payload, 0, sizeof(frame->payload));
	frame->length = 0;
	frame->inf.payload = frame->payload;
}








router_frame_t router_frame;

int router_queue_push(uint8_t src, uint8_t dest, uint8_t reply, void* payload, uint16_t length){
	router_frame_reset(&router_frame);
	t1_inf_t* inf = &router_frame.inf;
	inf->header.source = src;
	inf->header.destination = dest;
	inf->header.reply = reply;
	memcpy(inf->payload, payload, length);
	router_frame.length = length;
	return 0;
}

int router_queue_push_inf(t1_inf_t* inf, uint16_t len){
	const payload_header_t* h = &inf->header;
	return router_queue_push(h->source, h->destination, h->reply, inf->payload, len);
}

int ext_app_proc(uint8_t wdt, t1_inf_t* cmd, uint16_t clen, t1_inf_t* resp, uint16_t* rlen){
	int ret;
	uint32_t cnt = 0;
	t1_inf_t* inf;
	uint16_t len;
	
	router_queue_push_inf(cmd, clen);
	while(cnt < 100){
		cnt++;
		inf = &router_frame.inf;
		len = router_frame.length;
		if(inf->header.destination == NODE_EXT_APP){
			resp->header = inf->header;
			memcpy(resp->payload, inf->payload, len);
			*rlen = len;
			return 0;
		}
		ret = router_route(inf, len);
		if(ret){
			break;
		}
	}
	
	return -1;
}

int set_detected_card_info(void) {
    asn1_builder_t build_set_detected_card_info;
    ASN1(build_set_detected_card_info, ->TAG(SAMCOMMAND)
                                     ->TAG(SAMCOMMAND_SET_DETECTED_CARD_INFO)
                                     ->TAG(DETECTED_CARD_INFO)
                                     ->TAG(PROTOCOL)
                                     ->VALUE(PROTOCOL_APDU_OVER_BLE)
                                     ->CLOSE()
                                     ->TAG(CSN)
                                     ->VALUE({0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF})
                                     ->CLOSEALL());

    t1_inf_t inf = {.header = {.destination = NODE_SAM,
                               .source = NODE_EXT_APP,
                               .reply = NODE_EXT_APP,
                               .secure_channel = 0,
                               .RFU1 = 0,
                               .RFU2 = 0},
                    .payload = build_set_detected_card_info.payload};
	static uint8_t rbuf[512];
	t1_inf_t r_inf = {.payload = rbuf,};
	uint16_t rlen = 0;
	int ret = ext_app_proc(0, &inf, build_set_detected_card_info.dataPtr, &r_inf, &rlen);
	if(ret){
		LOG_E("error: %d", ret);
	}
	else{
		LOG_B("ok", r_inf.payload, rlen, 16);
	}
	return ret;
}
#if 1
int get_content_element_2(void) {
    asn1_builder_t build_get_content_element2;
    ASN1(build_get_content_element2, ->TAG(SAMCOMMAND)
                                   ->TAG(SAMCOMMAND_GET_CONTENT_ELEMENT2)
                                   ->TAG(CONTENT_ELEMENT_TAG)
                                   ->VALUE(IMPLICIT_FORMAT_PHYSICAL_ACCESS_BITS)
                                   ->CLOSE()
                                   ->TAG(EXIT_RF_ACTION)
                                   ->VALUE(EXIT_RF_ACTION_NONE)
                                   ->CLOSEALL());

    t1_inf_t inf = {.header = {.destination = NODE_SAM,
                               .source = NODE_EXT_APP,
                               .reply = NODE_EXT_APP,
                               .secure_channel = 0,
                               .RFU1 = 0,
                               .RFU2 = 0},
                    .payload = build_get_content_element2.payload};

	static uint8_t rbuf[512];
	t1_inf_t r_inf = {.payload = rbuf,};
	uint16_t rlen = 0;
	int ret = ext_app_proc(0, &inf, build_get_content_element2.dataPtr, &r_inf, &rlen);
	if(ret){
		LOG_E("error: %d", ret);
	}
	else{
		LOG_B("ok", r_inf.payload, rlen, 16);
	}
	return ret;

}
#endif 
#endif 


/*============================================================================================*/


TEST_GROUP(HIDBLE);


TEST_SETUP(HIDBLE)
{
}

TEST_TEAR_DOWN(HIDBLE)
{
}


IGNORE_TEST(HIDBLE, SEPowerOn)
{
	uint8_t atr[32];
	uint8_t alen;
	int ret;
	for( int i = 0; i < 10; i++){
		Connector_Init();
		CharacterModule_Init();
		Slot_Init();
		ret = Slot_PowerOn(Slot, atr, &alen);
		if(!ret){
			break;
		}
		BSP_Sleep_Ms(500);
	}
	TEST_ASSERT_EQUAL_INT_MESSAGE(0, ret, "PowerOn fail!");
	if(!ret){
		LOG_B("atr:", atr, alen, 8);
	}
}


IGNORE_TEST(HIDBLE, SEGetVersion)
{
	int i;

	for(i = 0; i < 1000; i++){
		IClass_PowerOff();
		BSP_Sleep_Ms(500);
		int ret = IClass_PowerOn();
		uint8_t ver[64];
		uint8_t vlen;
		ret = IClass_GetSEVersion(ver, &vlen);
		if(!ret){
			LOG_B("ver:", ver, vlen, 8);
			break;
		}
	}

}
#if 1

#define BLE_STATE_CONNECTED		0x01
#define BLE_STATE_NOTIFY_EN		0x02
#define BLE_STATE_HANDLE_VALID		0x04

#define BLE_STATE_OK	(BLE_STATE_CONNECTED|BLE_STATE_NOTIFY_EN|BLE_STATE_HANDLE_VALID)

#if 0
TEST(HIDBLE, GetPAC)
{
	int ret;
	uint8_t buf[64];
	uint8_t* resp;
	uint8_t rlen;
	for(int i = 0; i < 10000; i++){
		IClass_PowerOff();
		BSP_Sleep_Ms(500);
		ret = IClass_PowerOn();
		if(ret){
			continue;
		}
		uint8_t states[2];
		while(1){
			BSP_Sleep_Ms(1000);
			states[0] = states[1] = 0;
			hid_ble_get_state(states, 1000);
			if((states[1] & BLE_STATE_OK) == BLE_STATE_OK){
				break;
			}
		}
		ret = set_detected_card_info();
		if(!ret){
			ret = get_content_element_2();
		}
		if(!ret){
			hid_ble_eot(1000);
		}
		BSP_Sleep_Ms(5000);
	}
}
#endif 
TEST(HIDBLE, GetPAC)
{
	int ret;
	uint8_t buf[64];
	uint8_t rlen;
	for(int i = 0; i < 10000; i++){
		ret = rhb_poll(buf, &rlen);
		if(ret){
			BSP_Sleep_Ms(200);
			continue;
		}
		LOG_B("mac:", buf, rlen, 8);
		ret = rhb_get_pacs(buf, &rlen);
		if(ret < 0){
			BSP_Sleep_Ms(100);
		}
		else{
			BSP_Sleep_Ms(200);
		}
	}
}



#endif 


